/*
 *MIT License
 *
 *Copyright (c) 2019 chenshuai cs4380@163.com
 *
 *Permission is hereby granted, free of charge, to any person obtaining a copy
 *of this software and associated documentation files (the "Software"), to deal
 *in the Software without restriction, including without limitation the rights
 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *copies of the Software, and to permit persons to whom the Software is
 *furnished to do so, subject to the following conditions:
 *
 *The above copyright notice and this permission notice shall be included in all
 *copies or substantial portions of the Software.
 *
 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *SOFTWARE.
 */

package com.cs.cslc.common.rest;

import com.cs.cslc.common.biz.BaseBiz;
import com.cs.cslc.common.constant.HttpStatusConstant;
import com.cs.cslc.common.constant.MessageConstant;
import com.cs.cslc.common.msg.ObjectResultResponse;
import com.cs.cslc.common.msg.TableResultResponse;
import com.cs.cslc.common.pojo.ParamQuery;
import com.cs.cslc.common.util.StringEscapeEditor;
import com.cs.cslc.common.validate.AddField;
import com.cs.cslc.common.validate.UpdateField;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * BaseController 前端控制器基类.
 * <p>
 * 单表操作基础接口，可重写biz层单表操作，满足业务需求
 * </p>
 *
 * @param <Biz>    业务逻辑层
 * @param <Entity> 实体
 * @param <PK>     主键id数据类型
 * @author cs
 * @version 1.0
 * @date 2018年11月29日
 * @description
 */
@RestController
public class BaseController<Biz extends BaseBiz, Entity, PK> {

    @Autowired
    protected HttpServletRequest request;

    @Autowired
    protected Biz baseBiz;

    /**
     * 解决类型转换问题
     * TODO 待研究
     *
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new StringEscapeEditor());
        binder.registerCustomEditor(String[].class, new StringEscapeEditor());
    }

    /**
     * 新增单个对象
     *
     * @param entity 对象实体
     * @return
     */
    @PostMapping
    @ApiOperation("新增单个对象")
    public ObjectResultResponse<Entity> create(@RequestBody @Validated({AddField.class}) @ApiParam("实体对象") Entity entity,
                                               BindingResult bindingResult) {
        ObjectResultResponse<Entity> result = new ObjectResultResponse<>();

        // 判单验证
        if (bindingResult.hasErrors()) {
            result.setStatus(HttpStatusConstant.FAIL);
            result.setMessage(MessageConstant.MVC_VALIDATE_MSG);
            return result;
        }

        try {
            baseBiz.insertSelective(entity);
            result.setData(entity);
        } catch (Exception e) {
            result.setStatus(HttpStatusConstant.FAIL);
            result.setMessage(e.getMessage());
        }
        return result;
    }

    /**
     * 更新单个对象
     * <p>
     * 根据主键更新属性不为null的值
     * 注意：id参数不做业务处理，只是为了符合restful规范
     *
     * @param id     主键
     * @param entity 实体对象
     * @return
     */
    @PutMapping("/{id}")
    @ApiOperation("更新单个对象")
    public ObjectResultResponse<Entity> update(@PathVariable("id") @ApiParam("主键") PK id,
                                               @RequestBody @Validated(UpdateField.class) @ApiParam("实体对象") Entity entity,
                                               BindingResult bindingResult) {
        ObjectResultResponse<Entity> result = new ObjectResultResponse<>();
        if (null == id || StringUtils.isBlank(id.toString())) {
            result.setStatus(HttpStatusConstant.FAIL);
            result.setMessage("请选择待更新的数据！");
            return result;
        }
        // 判单验证
        if (bindingResult.hasErrors()) {
            result.setStatus(HttpStatusConstant.FAIL);
            result.setMessage(MessageConstant.MVC_VALIDATE_MSG);
            return result;
        }

        try {
            baseBiz.updateSelectiveById(entity);
            result.setData(entity);
        } catch (Exception e) {
            result.setStatus(HttpStatusConstant.FAIL);
            result.setMessage(e.getMessage());
        }
        return result;
    }

    /**
     * 通过主键获取对象信息
     *
     * @param id 主键
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("查询单个对象")
    public ObjectResultResponse<Entity> getEntityById(@PathVariable("id") @ApiParam("主键") PK id) {
        ObjectResultResponse<Entity> result = new ObjectResultResponse<>();
        try {
            ParamQuery query = new ParamQuery();
            query.put("id", id);
            Object o = baseBiz.selectOne(query);
            result.data((Entity) o);
        } catch (Exception e) {
            result.setStatus(HttpStatusConstant.FAIL);
            result.setMessage(e.getMessage());
        }
        return result;
    }


    /**
     * 删除单个对象
     *
     * @param id 主键
     * @return
     */
    @DeleteMapping("/{id}")
    @ApiOperation("删除单个对象")
    public ObjectResultResponse<Entity> remove(@PathVariable("id") @ApiParam("主键") PK id) {
        ObjectResultResponse<Entity> result = new ObjectResultResponse<>();
        try {
            baseBiz.deleteById(id);
        } catch (Exception e) {
            result.setStatus(HttpStatusConstant.FAIL);
            result.setMessage(e.getMessage());
        }
        return result;
    }

    /**
     * 分页获取数据列表
     *
     * @param params 查询条件
     * @return
     */
    @GetMapping
    @ApiOperation("分页获取数据列表")
    public TableResultResponse<Entity> list(@RequestParam @ApiParam("查询条件") Map<String, Object> params) {
        ParamQuery query = new ParamQuery(params);
        return baseBiz.selectTableByParamQuery(query);
    }
}